<?php

namespace App\Domain\Customer\Services;

use App\Domain\Customer\Dao\CustomerDao;
use App\Domain\Customer\Models\CustomerModel;
use App\Domain\FamilyMember\Dao\FamilyMemberDao;
use App\Exceptions\BadRequestException;
use App\Exceptions\JsonResponse\JsonResponseException;
use Illuminate\Support\Carbon;
use App\Exceptions\ServiceException;
use Illuminate\Support\Facades\Cache;
use Tymon\JWTAuth\Facades\JWTAuth;
use Illuminate\Database\Eloquent\Builder;
use function create_uuid;

class CustomerService
{
    /**
     * 生成盐值
     * @return string
     */
    public function generateSalt()
    {
        return \Str::random(16);
    }

    /**
     * 验证密码是否正确
     * @param $password
     * @param $salt
     * @param $correctPassword
     * @return bool
     */
    public function checkPassword($password, $salt, $correctPassword)
    {
        return $this->encryptionPassword($password, $salt) == $correctPassword;
    }

    /**
     * 加密密码
     * @param $password
     * @param $salt
     * @return string
     */
    public function encryptionPassword($password, $salt)
    {
        return md5($password . $salt);
    }


    /**
     * 登录
     * @param $params
     * @return array
     */
    public function Login($params)
    {
        $manager = new CustomerService();
        $dao = new CustomerDao();
        $customerModel = $dao->findByPhone($params['phone']);
        if (empty($customerModel))
            throw new BadRequestException('账号不存在');
        if (!$manager->checkPassword($params['password'], $customerModel->salt, $customerModel->password))
            throw new BadRequestException('账号或密码错误');
        if ($customerModel->status == 0)
            throw new BadRequestException('账号已禁用');
        if (!$token = auth('api')->login($customerModel))
            throw new ServiceException('登录失败');
        //登录记录
        $dao->update($customerModel, [
            'last_login_time' => Carbon::now()->toDateTimeString(),
            'last_login_ip' => request()->getClientIp(),
        ]);
        $data = [
            'token' => $token,
            "name" => $customerModel->name,
        ];
        return $data;
    }


    //创建用户
    public function createUser($param)
    {
        $customerDao = new CustomerDao();
        $data = $customerDao->findByPhone($param['phone']);
        if ($param['phone'] === $data['phone']) {
            throw new BadRequestException('账号已存在');
        }
        $code = $this->getCode($param['phone']);
        if ($param['code'] != $code) {
            throw new BadRequestException('验证码不正确');
        }
        $res = $customerDao->create([
            'id' => create_uuid(),
            'name' => $param['name'],
            'phone' => $param['phone'],
            'age' => $param['age'],
            'salt' => $salt = $this->generateSalt(),
            'password' => md5($param['password'] . $salt),
            'weight' => $param['weight'],
            'height' => $param['height'],
            'gender' => $param['gender'],
            'where' => '小健机器人'
        ]);
        $token = ['token' => 'Bearer ' . $this->Login($param)['token']];
        $data = $customerDao->findByPhone($param['phone']);
        $r = [
            'id' => $data['id'],
            'houseHolder_id' => $data['id'],
            'name' => $res['name'],
            'phone' => $res['phone'],
            'age' => $res['age'],
            'idCard' => $res['idCard'],
            'gender' => $res['gender'],
            'height' => $res['height'],
            'weight' => $res['weight'],
            'houseHolder' => '1',
            'relation' => '0',
        ];
        $familyDao = new FamilyMemberDao();
        $re = $familyDao->create($r);
        return $token;
    }

    //修改用户密码
    public function update($param)
    {
        $customerDao = new CustomerDao();
        $res = $customerDao->findById($param['id']);
        if (empty($res)) {
            throw new BadRequestException('账号不存在');
        }
        $data = [
            'salt' => $salt = $this->generateSalt(),
            'password' => md5($param['newPassword'] . $salt)
        ];
        $res = $customerDao->update($res, $data);
        return $res;
    }

    public function findPassword($password)
    {
        $user = JWTAuth::parseToken()->touser();
        $customerDao = new CustomerDao();
        $data = $customerDao->findById($user['id']);
        $oldpassword = md5($password . $data['salt']);
        if ($oldpassword === $data['password']) {
            return $oldpassword;
        }
    }


    /**
     * 创建登录验证码并发送短信
     * @param string $phone
     * @return string
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function createsms(string $phone)
    {
        $code = '123456';
        $this->setCode($code, $phone);
        return $code;
    }

    /**
     * 设置验证码缓存
     * @param string $code
     * @param string $phone
     */
    private function setCode(string $code, string $phone)
    {
        $key = $this->getKey($phone);
        Cache::put($key, $code, 300);
    }

    /**
     * @param string $phone
     * @return string
     */
    private function getKey(string $phone)
    {
        return $phone . "_login_code";
    }

    /**
     * @param string $phone
     * @param string $verificationCode
     */
    public function validateOrFail(string $phone, string $verificationCode)
    {
        if (!$this->validate($phone, $verificationCode)) {
            throw new JsonResponseException("验证码错误");
        }
    }

    /**
     * 验证短信验证码是否正确
     * @param string $phone
     * @param string $code
     * @return bool
     */
    public function validate(string $phone, string $code)
    {
        $trueCode = $this->getCode($phone);
        if (!$trueCode) {
            throw new JsonResponseException("验证码已过期");
        }
        return $code == $trueCode;
    }

    /**
     * 获取登录验证码
     * @param string $phone
     * @return string
     */
    private function getCode(string $phone)
    {
        $key = $this->getKey($phone);
        if (Cache::has($key)) {
            return Cache::get($key);
        } else {
            return "";
        }
    }

    public function list($params)
    {
        $query = CustomerModel::query()
            ->orderBy('id', 'desc')
            ->select('user.*')
            ->where('user.status', 1);
        $query = $query->where(function (Builder $query) use ($params) {
            if (isset($params['name']))
                $query->where('name', $params['name']);
            if (isset($params['phone']))
                $query->where('phone', $params['phone']);
            if (isset($params['gender']))
                $query->where('gender', $params['gender']);
            if (isset($params['start_time']))
                $query->where('create_time', '>=', $params['start_time']);
            if (isset($params['end_time']))
                $query->where('create_time', '<=', $params['end_time']);
        });
        if (isset($params['pageSize']) && isset($params['currentPage'])) {
            return $query->paginate($params['pageSize'], ['*'], 'page', $params['currentPage']);
        } else {
            return $query->get();
        }
    }

}
